package com.ftg.learn.chapter20.jdbcpojo.util;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

/**
 * 完成对我们的数据处理
 * @author KangJx
 * @date 2021/9/6
 */
public abstract class AbsBaseJdbc<T> implements IJdbc<T> {

    private final String url = "jdbc:mysql://localhost:3306/learnmysql";
    private final String userName = "root";
    private final String password = "Love0913@kjx";

    /**
     * 添加方法
     * @param t1  表名，列名，值 ?
     * @return
     */
    @Override
    public int insert(T t1){
        String sql = this.createInsertSql();
        Object[] obj = new Object[0];
        try {
            obj = this.createParameter(t1);
        } catch (ClassNotFoundException | IntrospectionException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return this.doDML(sql,obj);
    }



    /**
     * 查询T表当中的全部数据
     * @return
     */
    @Override
    public List<T> selectAll(){
        return null;
    }

    /**
     * 可以完成排序等操作
     * 用处理静态sql
     * @param or
     * @return
     */
    @Override
    public List<T> selectAll(Supplier<String> or){
        return null;
    }


    /**
     * 用处理静态sql带条件的
     * @param o
     * @return
     */
    @Override
    public List<T> selectAll(Supplier<String> o,Object...obj){
        return null;
    }



    /**
     * 用来生成基于添加的sql
     * @return sql
     */
    private String createInsertSql(){
       StringBuilder sb = new StringBuilder("insert into ");
       StringBuilder why = new StringBuilder();
        try {
            List<String> lis = this.getColsName();
            sb.append(this.getTableName()).append(" (");
            for(int i = 0 ,len = lis.size();i < len;i++){
                sb.append(lis.get(i)).append(i == len - 1?"":",");
                why.append("?").append(i == len - 1?"":",");
            }
            sb.append(") values (").append(why.toString()).append(")");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    /**
     * 为添加方法创建参数的
     * @param t1  dept一个实例  D
     * @return
     * @throws ClassNotFoundException
     * @throws IntrospectionException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private Object[] createParameter(T t1) throws ClassNotFoundException, IntrospectionException, InvocationTargetException, IllegalAccessException {
        Class c = t1.getClass();
        Field[] fs = c.getDeclaredFields();
        Object[] obj = new Object[fs.length];
        int index=0;
        for(Field f : fs){
            PropertyDescriptor pd = new PropertyDescriptor(f.getName(), c);
            Method getmethod = pd.getReadMethod();
            obj[index++] = getmethod.invoke(t1);
        }
        return obj;
    }

    /**
     * 取到当前类的泛型 ，做为表名来使用
     * @return 表名
     */
    private String getTableName() throws ClassNotFoundException {
        return getParameterTypeClass().getSimpleName();
    }

    /**
     * 泛型的反射
     * @return
     * @throws ClassNotFoundException
     */
    private Class getParameterTypeClass() throws ClassNotFoundException {
        ParameterizedType t2 = (ParameterizedType)this.getClass().getGenericSuperclass();
        Type[] type = t2.getActualTypeArguments();
        String classPath = type[0].getTypeName();
        return Class.forName(classPath);
    }

    /**
     * 获取泛型当中的全部列
     * @return
     * @throws ClassNotFoundException
     */
    private List<String> getColsName() throws ClassNotFoundException {
        ParameterizedType t2 = (ParameterizedType)this.getClass().getGenericSuperclass();
        Type[] type = t2.getActualTypeArguments();
        String classPath = type[0].getTypeName();
        Class c = Class.forName(classPath);
        Field[] fs = c.getDeclaredFields();
        List<String> cols = new ArrayList<>(fs.length);
        for(Field f : fs){
           cols.add(f.getName());
        }
        return cols;
    }

    /**
     * 完成数据库里面的所有dml操作
     * @param sql  语句
     * @param obj  值
     * @return     正整数 | -1 （没有影响）
     */
    public int doDML(String sql,Object...obj){
        try(
                Connection conn = DriverManager.getConnection(url,userName,password);
                PreparedStatement pstmt = conn.prepareStatement(sql);
        ){
            if(obj != null){
                for(int i = 0 ,len = obj.length;i < len;i++){
                    pstmt.setObject(i + 1 , obj[i]);
                }
            }
            return pstmt.executeUpdate();
        }catch (SQLException e) {
            e.printStackTrace();
        }
        return -1;
    }
}
